<?php

// This class is used to work out whether the user is able to save resources in particular locations based on content they contain.

class asset {

	private $m_userObj;
	
	private $m_childAssets = array("charts" => array(), "images" => array(), "imagesets" => array());
	private $m_restrictedAssets = array("charts" => array(), "images" => array(), "imagesets" => array());
	
	private $m_saveLocation;
	private $m_saveType;
	
	private $m_resourceType;
	
	private $m_assetID;
	private $m_targetID;
	
	private $m_newName;
	private $m_newDescription;
	
	public $m_hasGroupImages;
	public $m_hasPrivateImages;
	
	public $m_errorMessage;
	
	// setResource() $type
	const CHART 	= 1;
	const IMAGESET 	= 2;
	const IMAGE 	= 3;
	const BOOK 		= 4;
	
	// setResource() $saveType
	const RESOURCE_EXISTING = 1;
	const RESOURCE_NEW 		= 2;

	// setLocation() $location
	const LOCATION_PRIVATE 	= 1;
	const LOCATION_GROUP 	= 2;
	const LOCATION_PUBLIC 	= 3;
	const LOCATION_CURRENT	= 4;

	public function __construct(user &$userObj){
		$this->m_userObj = $userObj;
	}
	
	public function setResource($type, $saveType = asset::RESOURCE_NEW, $id = 0){
		if(is_integer($type) == false || is_integer($saveType) == false || is_integer($id) == false) throw new PicBoardException("All arguments to this function must be integers.");
		$this->m_resourceType = $type;
		$this->m_saveType = $saveType;
		$this->m_assetID = $id;
	}

	public function setLocation($location = asset::LOCATION_CURRENT, $id = 0){
		if(is_integer($location) == false) throw new PicBoardException("All arguments to this function must be integers.");
		$this->m_saveLocation = $location;
		$this->m_targetID = $id;
	}
	
	// Only used for new assets
	public function setNewDetails($name, $description){
		$this->m_newName = $name;
		$this->m_newDescription = $description;
	}	
	
	
	// Can we publish this resource? returns a boolean.
	public function canPublish(){
	
		switch($this->m_resourceType){
		
			case asset::CHART:
				// If there are any images that are not mulberry we cannot publish.
				
				$this->m_hasPrivateImages = false;
				
				$chart_pd = chart::isPublicDomain($this->m_userObj, $this->m_assetID);
	
				if($chart_pd['status'] == false) {
					$this->m_hasPrivateImages = true;
					$this->m_restrictedAssets['images'] = array_merge($this->m_restrictedAssets['images'], $chart_pd['images']);
					$this->m_restrictedAssets['charts'][$this->m_assetID] = chart::getChart($this->m_userObj, $this->m_assetID, true);
					return false;
				}
				
				// If the chart already exists in the public area deny
				// Get clones
				$chart_clones = chart::getClones($this->m_userObj, $this->m_assetID, book::LOCATION_PUBLIC);
				
				if(count($chart_clones) > 0) {
					$this->m_errorMessage = "You cannot publish this chart as it has already been published";
					return false;
				}
				
				return true;
			break;
			
			case asset::IMAGESET:
				return false;
			break;
			
			case asset::IMAGE:
				return false;
			break;
			
			case asset::BOOK:
				// We need to check what all the child assets contain. We cannot publish if they contain anything other than mulberry.
				$this->getChildren();
				if($this->m_hasPrivateImages){
					return false;
				} else {
					return true;
				}
			break;
		
		
		}
	
	}
	
	public function canDonate(){
	
		switch($this->m_resourceType){
		
			case asset::CHART:
				// If there are any images that are not mulberry we cannot donate.
				
				$this->m_hasPrivateImages = false;
				
				$chart_pd = chart::isPublicDomain($this->m_userObj, $this->m_assetID);
	
				if($chart_pd['status'] == false) {
					$this->m_hasPrivateImages = true;
					$this->m_restrictedAssets['images'] = array_merge($this->m_restrictedAssets['images'], $chart_pd['images']);
					$this->m_restrictedAssets['charts'][$this->m_assetID] = chart::getChart($this->m_userObj, $this->m_assetID, true);
					
					
					foreach($this->m_restrictedAssets['images'] as &$restrictedImage){
						$detectClone = images::getClones($this->m_userObj, $restrictedImage, images::LOCATION_GROUP, $this->m_targetID);
						
						// If there is a copy of this image in the group we don't need to report it as a restricted asset.
						if(count($detectClone > 0)) unset($restrictedImage);
						
						return false;
					}
				} else {
					return true;
				}
				
				
			break;
			
			case asset::IMAGESET:
				return false;
			break;
			
			case asset::IMAGE:
			
			break;
			
			case asset::BOOK:
				// We need to check what all the child assets contain. We cannot donate if they contain anything other than mulberry.
				$this->getChildren();
				if($this->m_hasPrivateImages){
					// If there are private images we need to detect if there are clones of these in the target group.
					// If there is clones, we can ignore any errors (as the images have already been donated)
					// But we'll need to change the ID's over to the clones for this group.
					
					foreach($this->m_restrictedAssets['images'] as &$restrictedImage){
						$detectClone = images::getClones($this->m_userObj, $restrictedImage, images::LOCATION_GROUP, $this->m_targetID);
						
						// If there is a copy of this image in the group we don't need to report it as a restricted asset.
						if(count($detectClone > 0)) unset($restrictedImage);
					}
					
					return false;
					
				} else {
					return true;
				}
			break;	
		
		}
	}
	
	public function canRetrieve(){
	
		switch($this->m_resourceType){
		
			case asset::CHART:
				// User can retrieve an asset if they are the originator of this asset.
				$originator = chart::getOriginator($this->m_assetID);

				if( $originator['uID'] == $this->m_userObj->getuID() ) return true;
				return false;
			break;
			
			case asset::IMAGESET:
			
			break;
			
			case asset::IMAGE:
				$originator = images::getOriginator($this->m_assetID);
				
				if( $originator['uID'] == $this->m_userObj->getuID() ) return true;
				return false;
			break;
			
			case asset::BOOK:
				// User can retrieve an asset if they are the originator of this asset.
				$originator = book::getOriginator($this->m_assetID);

				if( $originator['uID'] == $this->m_userObj->getuID() ) return true;
				return false;
			break;
		
		}	
	}
	
	public function canDelete(){}
	
	public function canSave(){
		switch($this->m_resourceType){
		
			case asset::CHART:
				// It depends on where we're saving as to whether this operation will succeed or fail.
				switch($this->m_saveLocation){

					case asset::LOCATION_PRIVATE:
						$existing_chart = chart::getChart($this->m_userObj, $this->m_assetID);
						
						if($existing_chart['name'] == $this->m_newName) throw new PicBoardException("The new name of this book is the same as the original - they must be different.");
						
						return true;
					break;
					
					case asset::LOCATION_GROUP:
					
					break;
					
					case asset::LOCATION_PUBLIC:
					
					break;
					
					case asset::LOCATION_CURRENT:
						// We can save in the current location if the asset has a different name to the original.
						// As its a book, we don't need to alter any of its children, but we do need to link the charts to the new book.
						
						// First off, is the new name different?
						$existing_chart = chart::getChart($this->m_userObj, $this->m_assetID);
						
						if($existing_chart['name'] == $this->m_newName) throw new PicBoardException("The new name of this book is the same as the original - they must be different.");
						
						return true;
					break;
				
				}
			break;
			
			case asset::IMAGESET:
			
			break;
			
			case asset::IMAGE:
			
				switch($this->m_saveLocation){
				
					case asset::LOCATION_CURRENT:
						return true;
				
					break;
				
				}
			
			break;
			
			case asset::BOOK:
				// It depends on where we're saving as to whether this operation will succeed or fail.
				switch($this->m_saveLocation){

					case asset::LOCATION_PRIVATE:
						$existing_book = book::getBook($this->m_userObj, $this->m_assetID);
						
						if($existing_book['name'] == $this->m_newName) throw new PicBoardException("The new name of this book is the same as the original - they must be different.");
						
						return true;
					break;
					
					case asset::LOCATION_GROUP:
					
					break;
					
					case asset::LOCATION_PUBLIC:
					
					break;
					
					case asset::LOCATION_CURRENT:
						// We can save in the current location if the asset has a different name to the original.
						// As its a book, we don't need to alter any of its children, but we do need to link the charts to the new book.
						
						// First off, is the new name different?
						$existing_book = book::getBook($this->m_userObj, $this->m_assetID);
						
						if($existing_book['name'] == $this->m_newName) throw new PicBoardException("The new name of this book is the same as the original - they must be different.");
						
						return true;
					break;
				
				}
				
			break;
		
		}
	}
	
	
	private function getChildren(){
		// If we're looking at a container we need to work out the overall permissions, so return all the assets of this object if its a child.
		// Currently the only container is a book, but this may change in the future.
		if($this->m_resourceType == asset::BOOK){
			$charts = chart::getBookCharts($this->m_assetID, 500);
			$this->m_childAssets['charts'] = $charts;
			
			$this->m_hasPrivateImages = false;
			
			foreach($this->m_childAssets['charts'] as &$chartAsset){
				$chart_pd = chart::isPublicDomain($this->m_userObj, $chartAsset['chID']);
				
				$chartAsset['publicDomain'] = $chart_pd['status'];

				if($chart_pd['status'] == false) {
					$this->m_hasPrivateImages = true;
					$this->m_restrictedAssets['images'] = array_merge($this->m_restrictedAssets['images'], $chart_pd['images']);
					$this->m_restrictedAssets['charts'][$chartAsset['chID']] = $chartAsset;
				}
			}
						
		} else {
			return;
		}
	}
	
	public function get(){
		// Get all the details we have currently for this asset.
		return array("assetID" => $this->m_assetID, "childAssets" => $this->m_childAssets, "restrictedAssets" => $this->m_restrictedAssets, "hasPrivateImages" => $this->m_hasPrivateImages);
	}
	
	public function getMessage(){
		return $this->m_errorMessage;
	}

}

?>